package Tcp;

import javax.swing.tree.FixedHeightLayoutCache;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * 有链接服务器
 * 会再用户发起请求后和改用户保持联系，直到用户断开联系
 * 用户之间的流联系通过socket连接
 */

public class TcpEchoServer {
    //负责将用户和服务器建立起流连接
    ServerSocket serverSocket = null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("成功启动");

        //线程池的创建，ExecutorService这个接口提供了一些已经设置好值的线程池，使用使用方便
        ExecutorService executorService = Executors.newCachedThreadPool();

        //处理多个请求
        while(true) {
            //由serverSocket建立起连接 socket进行具体的逻辑操作
            //因为TCP是有连接的，所以在进行交流时需要进行连接
            Socket socket = serverSocket.accept();

            //基于多线程实现多个用户同时访问 每次有一个用户就创建一个线程太慢了，使用线程池
//            Thread thread = new Thread(() -> {
//                try {
//                    mainLogic(socket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            thread.start();

            executorService.submit(() -> {
                try {
                    mainLogic(socket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    private void mainLogic(Socket socket) throws IOException{
        //创建输出输入流连接 出了try就直接关闭对象
        try (OutputStream writer = socket.getOutputStream();
             InputStream read = socket.getInputStream()) {

            //直接使用不好用，套层壳子
            System.out.printf("%s : 连接成功\n", socket.getInetAddress());
            Scanner scanner = new Scanner(read);//输入
            PrintWriter writer1 = new PrintWriter(writer);//输出

            while (true) {

                /**
                 检查是否还有连接 用hasNextLine表示那么就要用hasnextline来输入 且会读入\n输出\n
                 hasNext、hasNextLine不可能返回false，只有true和阻塞两种结果
                 hasNext、hasNextLine会判断有无输入，并且hasNext一直敲回车而不输入字符会导致线程阻塞
                 */
                System.out.println("等待输入");
                if (!scanner.hasNextLine()) {
                    System.out.println("连接断开");
                    break;
                }

                System.out.println("qinei");
                //读取请求
                String request  = scanner.nextLine();

                //返回答复
                String response = process(request);

                //将回复输出给流
                writer1.println(response);

                //刷新缓冲区 保证数据写在了网卡中
                writer1.flush();

                //打印日志
                System.out.printf("[%s:%d] request = %s  response = %s\n",
                        socket.getInetAddress(), socket.getPort(), request, response);
            }
        } finally {
            //关闭连接
            socket.close();
        }
    }
    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer = new TcpEchoServer(8080);
        tcpEchoServer.start();
    }
}














